package com.szxx.suit.fourtakesingle;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.szxx.constant.DdzCardTypes;
import com.szxx.constant.DdzCardConstant;
import com.szxx.domain.Card;
import com.szxx.domain.Cards;
import com.szxx.domain.DdzCard;
import com.szxx.suit.AbstractSuitTerm;
import com.szxx.suit.AbstractSuitType;
import com.szxx.suit.DdzAnalysisResult;
import com.szxx.suit.DdzSuitAnalyzer;
import com.szxx.suit.DdzTypeUtil;
import com.szxx.suit.bomb.BombTypeAnalyzer;
import com.szxx.suit.single.SingleTypeAnalyzer;

/**
 * 四带两张牌型 <br>
 *
 * @author Ambrose
 */
@Component
public class FourTakeSingleTypeAnalyzer extends DdzSuitAnalyzer {
	
	@Autowired
	private SingleTypeAnalyzer singleTypeAnalyzer;

	@Override
	public AbstractSuitType getSuitType() {
		return DdzCardTypes.FOUR_TAKE_SINGLE;
	}

	/** 元组数量 */
	private static int TUPLE_SIZE = 6;
	
	@Override
	protected boolean doCheckRule(Cards cards, AbstractSuitTerm term, DdzAnalysisResult result) {
		if (result.getCardNum() == TUPLE_SIZE) { // 六的倍数，考虑 444435
			if (result.isAllCardLazi()) { // 全是癞子
				return false;
			} else {
				List<Integer> allValues = result.getNoneLaziValueCounter().getAllValues(); // 非癞子的点数
				if (allValues.size() > 3) { // 四带二牌型最大只有3种点数
					return false;
				} else {
					int laiziCardNum = result.getLaziCardNum();
					for (Integer number : allValues) {
						int valueNum = result.getNoneLaziValueCounter().getValueCount(number);
						if (valueNum + laiziCardNum >= 4) { // 验证能够组成四张 23344*
							return true;
						}
					}
					return false;
				}
			}
		} else {
			return false;
		}
	}
	
	@Override
	protected List<Cards> doAnalysizeLaizi(Cards cards, AbstractSuitTerm term, boolean onlyMaxValue) {
		List<Cards> cardsResult = new LinkedList<Cards>();
		DdzAnalysisResult result = (DdzAnalysisResult) cards.getResult();
		List<Card> laiziCardList = new ArrayList<Card>(cards.subList(result.getCardNum() - result.getLaziCardNum(), result.getCardNum()));
		List<Integer> allValues = result.getNoneLaziValueCounter().getAllValues(); // 非癞子的点数
		int laiziCardNum = result.getLaziCardNum();
		if (laiziCardNum >= 4) { // 此时最多可能只有4个癞子，可组成任意牌型
			for (int valueTemp = DdzCardConstant.NUMBER_2_VALUE; valueTemp >= DdzCardConstant.NUMBER_3_VALUE; valueTemp--) {
				int valueTmepNum = result.getNoneLaziValueCounter().getValueCount(valueTemp);
				int needLaiziNum = 4 - valueTmepNum; // 需要填补几个癞子
				for (int i = 0; i < laiziCardList.size(); i++) {
					DdzCard ddzCard = (DdzCard) laiziCardList.get(i);
					if (i < needLaiziNum) {
						ddzCard.changeCard(valueTemp);
					} else {
						ddzCard.changeCard(ddzCard.getNumber());
					}
				}
				Cards cardsCopy = cards.clone();
				analysize(cardsCopy, term);
				cardsResult.add(cardsCopy);
				if (onlyMaxValue) {
					break; // 取完最大一组就跳出
				}
			}
		} else { // 455*** 456*** 444456
			for (int i = allValues.size() - 1; i >= 0; i--) { // 从大到小遍历
				int value = allValues.get(i);
				int valueNum = result.getNoneLaziValueCounter().getValueCount(value);
				int needLaiziNum = 4 - valueNum; // 需要填补几个癞子
				if (laiziCardNum >= needLaiziNum) { // 能够组成四张
					for (int j = 0; j < laiziCardList.size(); j++) {
						DdzCard ddzCard = (DdzCard) laiziCardList.get(j);
						if (j < needLaiziNum) {
							ddzCard.changeCard(value);
						} else {
							ddzCard.changeCard(ddzCard.getNumber());
						}
					}
					Cards cardsCopy = cards.clone();
					analysize(cardsCopy, term);
					cardsResult.add(cardsCopy);
					if (onlyMaxValue) {
						break; // 取完最大一组就跳出
					}
				}
			}
		}
		return cardsResult;
	}
	
	@Override
	protected boolean containsPossibleCards(Cards handCards, AbstractSuitTerm term) {
		return ((DdzAnalysisResult) handCards.getResult()).getCardNum() >= TUPLE_SIZE;
	}
	
	/** 最多使用癞子的数量 */
	private static int MAX_USE_LAIZI_CARD_NUM = 6;
	
	/** 防重复判定的比例值 参照 int key = count_3_value * TUPLE_WEIGHT + count_1_value_a + count_1_value_b; */
	private static int TUPLE_WEIGHT = 1000000;
	
	/** 癞子权重，区分癞子变成的5 和 原本就是5 */
	private static int LAIZI_WEIGHT = 1000;
	
	@Override
	protected List<Cards> doListPossibleCards(Cards handCards, AbstractSuitTerm term) {
		List<Cards> cardsResult = new LinkedList<Cards>();
		// 非癞子部分
		DdzAnalysisResult result = (DdzAnalysisResult) handCards.getResult();
		List<Card> noneLaiziCardList = handCards.subList(0, result.getNoneCardNum());
		Cards noneLaiziCards = DdzTypeUtil.createCardsCopy(noneLaiziCardList);
		noneLaiziCards.setResult(handCards.getResult().clone());
		DdzAnalysisResult noneLaiziCardsResult = (DdzAnalysisResult) noneLaiziCards.getResult();
		noneLaiziCardsResult.collectNumber(noneLaiziCards, term);
		// 癞子部分
		List<Card> laiziCardList = handCards.subList(result.getNoneCardNum(), result.getCardNum());
		Cards laiziCards = DdzTypeUtil.createCardsCopy(laiziCardList);
		laiziCards.setResult(handCards.getResult().clone());
		DdzAnalysisResult laiziCardsResult = (DdzAnalysisResult) laiziCards.getResult();
		laiziCardsResult.collectNumber(laiziCards, term);
		
		int maxLoseValue = 0; // 寻找最大遗失的牌 让***5可以出现，但是仅一次
		for (int valueTemp = DdzCardConstant.NUMBER_2_VALUE // 从小开始
				; valueTemp >= DdzCardConstant.NUMBER_3_VALUE; valueTemp--) {
			if (result.getNoneLaziValueCounter().getValueCount(valueTemp) == 0) {
				maxLoseValue = valueTemp;
				break;
			}
		}
		int laiziCardNum = result.getLaziCardNum();
		int maxUseLaiziCardNum = MAX_USE_LAIZI_CARD_NUM < laiziCardNum ? MAX_USE_LAIZI_CARD_NUM : laiziCardNum;
		Set<Integer> exsitKeys = new HashSet<Integer>(); // 记录已经组成三带一的value
		for (int useLaiziCardNum = 0; useLaiziCardNum <= maxUseLaiziCardNum; useLaiziCardNum++) {
			if (useLaiziCardNum < MAX_USE_LAIZI_CARD_NUM) { // 用了 0.1.2.3 个癞子
				for (int valueTemp = DdzCardConstant.NUMBER_3_VALUE // 从小开始
						; valueTemp <= DdzCardConstant.NUMBER_2_VALUE; valueTemp++) {
					Cards modelCardsCopy = noneLaiziCards.clone(); // 常规牌副本
					DdzAnalysisResult modelResultCopy = (DdzAnalysisResult) modelCardsCopy.getResult();
					List<Card> useLaiziCardList = DdzTypeUtil.cloneSublistedCards(laiziCards, 0, useLaiziCardNum); // 补癞子
					int valueTempNum = modelResultCopy.getNoneLaziValueCounter().getValueCount(valueTemp);
					int needLaiziCardNum = BombTypeAnalyzer.TUPLE_SIZE - valueTempNum;
					needLaiziCardNum = needLaiziCardNum > 0 ? needLaiziCardNum : 0;
					if (needLaiziCardNum == 0) {
						List<Card> removedCardList = DdzTypeUtil.cloneRemovedCards(modelCardsCopy, valueTemp, BombTypeAnalyzer.TUPLE_SIZE);
						Cards tupleCards = new Cards(removedCardList);
						Cards remainCards = DdzTypeUtil.cloneCardsAndAddCardList(modelCardsCopy, useLaiziCardList);
						List<Cards> takenCardsList = repeatSelectSingleCards(remainCards, 2, term);
						for (Cards takenCards : takenCardsList) {
							Cards resultCards = DdzTypeUtil.cloneCardsAndAddCards(tupleCards, takenCards);
							int key = valueTemp * TUPLE_WEIGHT;
							for (Card card : takenCards) {
								key += card.getValue();
								if (((DdzCard)card).isLazi()) { // 癞子权重，区分癞子变成的5 和 原本就是5
									key += card.getValue() * LAIZI_WEIGHT;
								}
							}
							if (!exsitKeys.contains(key) && match(resultCards, term)) {
								exsitKeys.add(key);
								// 保证排序
								((DdzAnalysisResult)resultCards.getResult()).setSortFirstValue(valueTemp);
								analysize(resultCards, term);
								cardsResult.add(resultCards);
							}
						}
					} else { // 需要癞子来拼凑
						if (needLaiziCardNum == BombTypeAnalyzer.TUPLE_SIZE 
								&& valueTemp != maxLoseValue) {
							// 这里是对癞子做tuple的去重
							// 否则会出现 ****带7799 既能是 3333带7799 也能是 4444带7799  5555带7799 
							continue;
						}
						if (useLaiziCardNum >= needLaiziCardNum) { // 癞子足够拼凑
							List<Card> removedCardList = DdzTypeUtil.cloneRemovedCards(modelCardsCopy, valueTemp, valueTempNum);
							for (int i = 0; i < needLaiziCardNum; i++) {
								DdzCard laiziCard = (DdzCard) useLaiziCardList.remove(0);
								laiziCard.changeCard(valueTemp);
								removedCardList.add(laiziCard);
							}
							for (Card laiziCard : useLaiziCardList) {
								((DdzCard)laiziCard).changeCard(laiziCard.getValue());
							}
							Cards tupleCards = new Cards(removedCardList);
							Cards remainCards = DdzTypeUtil.cloneCardsAndAddCardList(modelCardsCopy, useLaiziCardList);
							List<Cards> takenCardsList = repeatSelectSingleCards(remainCards, 2, term);
							for (Cards takenCards : takenCardsList) {
								Cards resultCards = DdzTypeUtil.cloneCardsAndAddCards(tupleCards, takenCards);
								int key = valueTemp * TUPLE_WEIGHT;
								for (Card card : takenCards) {
									key += card.getValue();
									if (((DdzCard)card).isLazi()) { // 癞子权重，区分癞子变成的5 和 原本就是5
										key += card.getValue() * LAIZI_WEIGHT;
									}
								}
								if (!exsitKeys.contains(key) && match(resultCards, term)) {
									exsitKeys.add(key);
									// 保证排序
									((DdzAnalysisResult)resultCards.getResult()).setSortFirstValue(valueTemp);
									analysize(resultCards, term);
									cardsResult.add(resultCards);
								}
							}
						}
					}
				}
			} else { // 用了 5个癞子
				for (int valueTemp = DdzCardConstant.NUMBER_3_VALUE // 从小开始
						; valueTemp <= DdzCardConstant.NUMBER_2_VALUE; valueTemp++) {
					Cards modelCardsCopy = laiziCards.clone(); // 常规牌补上癞子
					DdzAnalysisResult modelResultCopy = (DdzAnalysisResult) modelCardsCopy.getResult();
					if (modelResultCopy.getAllValueCounter().getValueCount(valueTemp) >= BombTypeAnalyzer.TUPLE_SIZE) {
						List<Card> removedCardList = DdzTypeUtil.cloneRemovedCards(modelCardsCopy, valueTemp, BombTypeAnalyzer.TUPLE_SIZE);
						Cards tupleCards = new Cards(removedCardList);
						List<Cards> takenCardsList = repeatSelectSingleCards(modelCardsCopy, 2, term);
						for (Cards takenCards : takenCardsList) {
							Cards resultCards = DdzTypeUtil.cloneCardsAndAddCards(tupleCards, takenCards);
							for (Card card : resultCards) {
								if (((DdzCard)card).hasNotChanged()) { // 有的经过处理已经被赋值了不能再改变
									((DdzCard)card).changeCard(card.getValue());
								}
							}
							if (match(resultCards, term)) {
								// 保证排序
								((DdzAnalysisResult)resultCards.getResult()).setSortFirstValue(valueTemp);
								analysize(resultCards, term);
								cardsResult.add(resultCards);
							}
						}
					}
				}
			}
		}
		return cardsResult;
	}

	/**
	 * 在固定牌组中寻找repeat张单牌 <br>
	 * 比如在 5。5。6。7 中寻找两张单牌 5.5 5.6 5.7 6.7   注意这里已经去重了 6.7 和 7.6 不会同时出现 
	 * 
	 * @param cards
	 * @param repeat
	 * @param term
	 * @param onlyMaxValue
	 * @return
	 */
	public List<Cards> repeatSelectSingleCards(Cards cards, int repeat, AbstractSuitTerm term) {
		Cards modelCards = DdzTypeUtil.cloneCardsAndAddCardList(cards, null); // 常规牌补上癞子
		DdzAnalysisResult modelResult = (DdzAnalysisResult) modelCards.getResult();
		modelResult.collectNumber(modelCards, term);
		if (modelResult.getCardNum() < repeat) { // 数量不足
			return new ArrayList<Cards>();
		}
		List<Cards> resultCardsList = singleTypeAnalyzer.listPossibleCards(modelCards, term); // 记录最终结果
		if (resultCardsList.size() != 0) {
			for (int i = 1; i < repeat; i++) { // 上面已经获取了一次了
				Set<Integer> exsitKeys = new HashSet<Integer>(); // 每一步都去重
				List<Cards> currentCardsList = new LinkedList<Cards>(resultCardsList);
				resultCardsList.clear(); // 清空上一步的结果
				for (Cards preCards : currentCardsList) {
					Cards remainCards = DdzTypeUtil.cloneCardsAndRemoveCards(modelCards, preCards);
					List<Cards> nextCardsList = singleTypeAnalyzer.listPossibleCards(remainCards, term);
					for (Cards nextCards : nextCardsList) {
						Cards combinedCards = DdzTypeUtil.cloneCardsAndAddCards(preCards, nextCards);
						int key = 0;
						for (Card card : combinedCards) {
							key += card.getValue();
							if (((DdzCard)card).isLazi()) { // 癞子权重，区分癞子变成的5 和 原本就是5
								key += LAIZI_WEIGHT;
							}
						}
						if (!exsitKeys.contains(key)) {
							exsitKeys.add(key);
							resultCardsList.add(combinedCards);
						}
					}
				}
			}
		}
		return resultCardsList;
	}

}
